/******************************************************************************
 * main.cpp: call optimization algorithms.
 *
 * Author: Pedro Henrique Del Bianco Hokama <hokama@ic.unicamp.br>
 * based on: Carlos Eduardo de Andrade <andrade@ic.unicamp.br>
 *
 * (c) Copyright 2011 Institute of Computing, University of Campinas.
 *     All Rights Reserved.
 *
 *  Created on : Oct 01, 2012 by hokama
 *
 * This software is licensed under the Common Public License. Please see
 * accompanying file for terms.
 *****************************************************************************/


/******************************************************************************
 * Nao coloque suas funcoes aqui. esse arquivo pode
 * ser substituido por outro padrao.
 * Voce deve implementar as funcoes
 *****************************************************************************/

#include <iostream>
#include <iomanip>
#include <list>
using namespace std;

#include <lemon/list_graph.h>
#include <lemon/lgf_reader.h>
using namespace lemon;

#include "timer.hpp"


#include "mySCPsolver/mySCPsolver.hpp"

//-------------------------------[ Main ]------------------------------------//

int main(int argc, char* argv[]) {
	SteinerConstrainedPathSolver* solver = new mySCPsolver();

    int timeLimit, status, exact;
    double delayLimit;

    //---------------------- Carrega uma instancia ----------------------//
    if (argc < 5){
    	cout << "Parametros incorretos\n";
    	return 0;
    }

    timeLimit = atoi(argv[2]);
    delayLimit = atof(argv[3]);
    exact = atof(argv[4]);

    if(!solver->loadInstance(argv[1], delayLimit))
        return -1;

    solver->displayInstance();

    //------------------- Checa se podemos ter caminhos -------------------//

    if(solver->haveTerminalLeaves()){
        cout << "\n\n--->> A instancia " << argv[1]
             << " nao tem solucao!!" << endl;
        return 0;
    }

    //---------------------- Exemplo de otimizacao ----------------------//

    Timer timer;
    timer.restart();

    if (exact == 1) status = solver->solve(timeLimit);
    else     status = solver->solveFast(timeLimit);


    //------------------------ Outras chamadas -------------------------//

    cout << "\nLB & UB & Solution Value & Time(s)\n"
         << solver->lb << " & "
         << solver->ub << " & " << solver->solution_value << " & " << timer.elapsed();


    //------------------ Testando a uma solucao --------------------//

    switch(solver->checkSolution(solver->best_solution, solver->solution_value)) {
    case SteinerConstrainedPathSolver::OK:
        cout << "\n\n++ solucao correta" << endl;
        break;

    case SteinerConstrainedPathSolver::INCORRECT_PATH:
        cout << "\n\n++ Caminho incorreto" << endl;
        break;

    case SteinerConstrainedPathSolver::INCORRECT_VALUE:
        cout << "\n\n++ valor do caminho incorreto" << endl;
        break;

    case SteinerConstrainedPathSolver::MISSING_TERMINALS:
        cout << "\n\n++ Caminho nao cobriu todos terminais" << endl;
        break;

    case SteinerConstrainedPathSolver::MISSING_ENDPOINTS:
        cout << "\n\n++ Caminho nao comeca e acaba em s e t" << endl;
        break;

    case SteinerConstrainedPathSolver::INCORRECT_DELAY:
        cout << "\n\n++ Caminho ultrapassa o atraso permitido" << endl;
        break;

    default:
        cout << "\n\n++ Erro desconhecido" << endl;

    }

    //--------------------- Exemplo de sa�da ---------------------//
    solver->displaySolution(solver->best_solution);

    char result = 'Y';

    // Formata a saida e imprime os resultados
    cout << setiosflags(ios::fixed) << setprecision(2)
         << "\nSolution & Time & Best Solution Value\n"
         << result << " & " << timer.elapsed()
         << " & "
         << (result != 'N'? solver->solution_value	 : 0.00) << endl;

    cout.flush();

    delete solver;
    return 0;
}
